package com.db.server;

import com.db.derby.DBAccess;
import com.db.history.messages.Message;
import com.db.history.messages.PrivateMessage;
import com.db.server.task.TaskGetHistory;
import com.db.server.task.TaskGetPrivateHistory;
import com.db.server.task.TaskGetRoomHistory;
import com.db.services.Settings;

import java.util.*;


public class ServerSession {
    private Map<RequestReceiver, ClientInfo> clients = new HashMap<RequestReceiver, ClientInfo>();
    private Map<String, RequestReceiver> clientsByName = new HashMap<String, RequestReceiver>();
    private Map<String, Set<RequestReceiver>> rooms = new HashMap<String, Set<RequestReceiver>>();
    //private MessageHistory MessageHistory = new MessageHistory();
    private DBAccess db;

    public ServerSession(DBAccess db) {
        this.db = db;
    }

    public synchronized void sendMessage(RequestReceiver client, String text) {
        Message message = new Message(clients.get(client).getRoom(), clients.get(client).getName(), text);
        db.addMessage(message);
        String room = clients.get(client).getRoom();
        for (RequestReceiver rr : rooms.get(room)) {
            rr.addServerMessage(message.toString());
        }
    }

    public synchronized void sendPrivateMessage(RequestReceiver client, String sendTo, String text) {
        PrivateMessage message = new PrivateMessage(clients.get(client).getRoom(),  clients.get(client).getName(), text, sendTo);
        RequestReceiver rr = clientsByName.get(sendTo);
        if (rr == null) {
            client.addServerMessage("No such user");
            return;
        }
        db.addPrivateMessage(message);
        rr.addServerMessage("Personally from " + getClientName(client) + "\n" + message);
        client.addServerMessage("Personally to " + getClientName(rr) + "\n" + message);
    }

    private String getClientName(RequestReceiver client) {
        return clients.get(client).getName();
    }

    public synchronized void addClient(RequestReceiver client) {
        clients.put(client, new ClientInfo(Settings.ANONYMOUS_NAME, Settings.GUEST_ROOM));

        if (rooms.get(Settings.GUEST_ROOM) == null)
            rooms.put(Settings.GUEST_ROOM, new HashSet<RequestReceiver>());

        rooms.get(Settings.GUEST_ROOM).add(client);
    }

    public synchronized void removeClient(RequestReceiver client) {
        clientsByName.remove(getClientName(client));
        removeClientFromRoom(client);
        clients.remove(client);
    }

    private void removeClientFromRoom(RequestReceiver client) {
        String room = clients.get(client).getRoom();
        Set<RequestReceiver> clientsInRoom = rooms.get(room);
        clientsInRoom.remove(client);
        if (clientsInRoom.isEmpty()) {
            rooms.remove(room);
        }
    }

    public synchronized boolean login(RequestReceiver client, String name, String password) {
        if (clientsByName.get(name) != null) {
            client.addServerMessage("user is already online");
            return false;
        }
        //clientsByName.remove(getClientName(client));
        if (!db.login(name, password)) {
            client.addServerMessage("wrong login or password");
            return false;
        }
        clients.get(client).setName(name);
        clientsByName.put(name, client);
        client.addServerMessage("nickname accepted");
        return true;
    }

    public synchronized void setRoomName(RequestReceiver client, String roomName) {
        removeClientFromRoom(client);
        if (rooms.get(roomName) == null) {
            rooms.put(roomName, new HashSet<RequestReceiver>());
            client.addServerMessage("Added new room:\t" + roomName);
        }
        rooms.get(roomName).add(client);
        clients.get(client).setRoom(roomName);
        client.addServerMessage("You are in room " + roomName);
    }

    public synchronized void getRoomList(RequestReceiver client) {
        if (rooms.isEmpty()) {
            client.addServerMessage("No rooms yet");
            return;
        }
        String roomNames = "";
        for (String roomName : rooms.keySet()) {
            roomNames += roomName + "\n";
        }
        client.addServerMessage(roomNames);
    }

    public synchronized void getHistory(RequestReceiver client) {
        client.addTask(new TaskGetHistory(db));
    }

    public synchronized void getRoomHistory(RequestReceiver client) {
        client.addTask(new TaskGetRoomHistory(db, clients.get(client).getRoom()));
    }

    public synchronized void getPrivateHistory(RequestReceiver client) {
        client.addTask(new TaskGetPrivateHistory(db, clients.get(client).getName()));
    }
}
